package com.novunda.tool.codec;

import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.Charset;

/**
 * 加解密
 *
 * @author linfeng
 * @since 2016/11/10
 */
public final class Codec implements Cloneable, Serializable {

    private static final long serialVersionUID = -7057015256582845751L;

    /**
     * 秘钥生成对象
     *
     * @return 秘钥生成对象
     */
    public static KeyPairGenerator keyPair() {
        return new DefaultKeyPairGenerator();
    }

    /**
     * 非对称加密
     *
     * @param key 公钥
     * @return 加密对象
     */
    public static Encrypt asymmetricEncrypt(String key) {
        return new DefaultAsymmetricEncrypt(key);
    }

    /**
     * 对称加密
     *
     * @param key 私钥
     * @return 加密对象
     */
    public static Encrypt symmetricEncrypt(String key) {
        return new DefaultSymmetricEncrypt(key);
    }

    /**
     * 非对称解密
     *
     * @param key 私钥
     * @return 解密对象
     */
    public static Decrypt asymmetricDecrypt(String key) {
        return new DefaultAsymmetricDecrypt(key);
    }

    /**
     * 非对称解密
     *
     * @param key 私钥
     * @return 解密对象
     */
    public static Decrypt symmetricDecrypt(String key) {
        return new DefaultSymmetricDecrypt(key);
    }

    private static class DefaultAsymmetricEncrypt implements Encrypt {

        private String CHARSET_UTF8 = "UTF-8";
        private String publicKey;

        public DefaultAsymmetricEncrypt(String publicKey) {
            this.publicKey = publicKey;
        }

        public String encrypt(String plainText) {
            String enc = null;
            try {
                enc = SM2Utils.encrypt(Util.hexToByte(publicKey), plainText.getBytes(Charset.forName(CHARSET_UTF8)));
            } catch (IOException e) {
                e.printStackTrace();
            }
            return enc;
        }

    }

    private static class DefaultSymmetricEncrypt implements Encrypt {

        private SM4Utils sm4 = new SM4Utils();

        public DefaultSymmetricEncrypt(String publicKey) {
            sm4.setSecretKey(publicKey);
        }

        public String encrypt(String plainText) {
            return sm4.encryptData_ECB(plainText);
        }
    }

    private static class DefaultAsymmetricDecrypt implements Decrypt {

        private String privateKey;

        public DefaultAsymmetricDecrypt(String privateKey) {
            this.privateKey = privateKey;
        }

        public String decrypt(String cipherText) {
            String dec = null;
            try {
                byte[] decryptByte = SM2Utils.decrypt(Util.hexToByte(privateKey), Util.hexToByte(cipherText));
                if (decryptByte != null) {
                    dec = new String(decryptByte);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return dec;
        }
    }

    private static class DefaultSymmetricDecrypt implements Decrypt {

        private SM4Utils sm4 = new SM4Utils();

        public DefaultSymmetricDecrypt(String publicKey) {
            sm4.setSecretKey(publicKey);
        }

        public String decrypt(String cipherText) {
            return sm4.decryptData_ECB(cipherText);
        }

    }

    private static class DefaultKeyPairGenerator implements KeyPairGenerator {

        public KeyPair generator() {
            return SM2Utils.generateKeyPair();
        }
    }

}
